#include "snetwork/NluList.h"

namespace Sock
{   
    CNluList *CNluList::m_instance = NULL;

    CNluList *CNluList::instance()
    {
        if (m_instance==NULL) {
            m_instance = new CNluList();
        }
        return m_instance;
    }
    
    CNluList::CNluList()
    {
        
    }    
    
    /**
     * @return http_chain_t *head   head node 
     */
    http_chain_t *CNluList::createList_L()
    {              
        http_chain_t *head;  
        head = (http_chain_t *) malloc (sizeof(http_chain_t));        
        head->next = NULL;        

        return head;
    }
    
    /**
     * @param http_chain_t *q       prev node
     * @param http_buf_t *b         need to save struct
     * @param size_t file           need to send file
     * @return http_chain_t *p      now create node

     */
    http_chain_t *CNluList::listInsert_L(http_chain_t *out_head, http_chain_t *q, 
                    http_buf_t *b, long len, http_file_t *file)
    {
        http_chain_t *p;

        p = (http_chain_t *) malloc (sizeof(http_chain_t));        
        p->buf = (http_buf_t *) malloc (sizeof(http_buf_t));
        p->buf->start = (char *) malloc (len+1);

        memset(p->buf->start, 0, len+1);        
        strncpy(p->buf->start, b->start, len);
        p->buf->last  = p->buf->start;
	    p->buf->end   = p->buf->start + len;
        
        p->buf->file = file;
        p->buf->in_file = 1;
        
        //llog("p->buf->file->fd:%d", p->buf->file->fd);
        
        p->next = q->next;
        q->next = p;
        q = p;
        
        // if struct is null
        if (out_head->next == NULL) {
            out_head->next = q;
        }
        
        return q;   
    }
    
    /**
     * @param http_chain_t *q       prev node
     * @param http_buf_t *b         need to save struct
     * @param size_t len            need malloc length of b->start 
     * @return http_chain_t *p      now create node
     */
    http_chain_t *CNluList::listInsert_L(http_chain_t *out_head, http_chain_t *q, http_buf_t *b, size_t len)
    {
        http_chain_t *p;
        
        p = (http_chain_t *) new http_chain_t[1];        
        p->buf = (http_buf_t *) new http_buf_t[1];
        p->buf->start = (char *) new char[len+1];
        
        memset(p->buf->start, 0, len+1);
        
        strncpy(p->buf->start, b->start, len);
        p->buf->last  = p->buf->start;
	    p->buf->end   = p->buf->start + len;
        p->buf->in_file = 0;
        
        p->next = q->next;
        q->next = p;
        q = p;
        
        // if struct is null
        if (out_head->next == NULL) {
            out_head->next = q;
        }
        
        return q;    
    }   
    
    /**
     * @param http_chain_t *q               prev node or header node
     *        http_chain_t *p               need to delete node
     *
     * @return void     
     */
    void CNluList::CListDelete_L(http_chain_t *head, http_chain_t *p)
    {   
        // prev node point to p's next node
        head->next = p->next;             

        // free space
        if (p->buf->in_file) {
            close(p->buf->file->fd);
            delete p->buf->file;
        }
        //llog("p->buf->start:%s", p->buf->start);
        
        delete [] p->buf->start;        
        delete p->buf;
        delete p;
    }
    
    /**
     *  **drop disp**
     * @param http_chain_t *head    head node
     * @return void
     */
    void CNluList::listDrop_L(http_chain_t *head)
    {
        http_chain_t *p = head->next;
        
        if (p == NULL)
            return;
            
        while (p) {
        
            if (p->buf->file) {
                close(p->buf->file->fd);
                delete p->buf->file;
            }
            
            delete [] p->buf->start;
            p->buf->start = NULL;
            delete p->buf;
            delete p;
                        
            p->buf = NULL;
            p = NULL;
        
            p = p->next;
        }
    }
}
